package dviz.visualAspect;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;

public class AnnotationHelper {
	public static HashMap<Object, Object> annotationRepository = new HashMap<Object, Object>();

	public static boolean existsSetter(Class clazz, String name) {
		Method method[] = clazz.getMethods();
		Method target = null;
		for (Method m : method) {
			if (m.getName().equalsIgnoreCase(("set" + name))) {
				target = m;
				break;
			}
		}
		if (target == null)
			return false;
		return true;
	}

	public static Method findInvokeFunction(Object context, String name) {
		Class clazz = context.getClass();
		Method method[] = clazz.getMethods();
		Method target = null;
		for (Method m : method) {
			if (m.getName().equalsIgnoreCase(name)
					&& m.getParameterTypes().length == 1
					&& m.getParameterTypes()[0].equals(HashMap.class)) {
				target = m;
				break;
			}
		}
		if (target == null)
			return null;
		return target;
	}

	public static Object invokeFunction(Object context, String name) {
		Class clazz = context.getClass();
		try {
			Method method[] = clazz.getMethods();
			Method target = null;
			for (Method m : method) {
				if (m.getName().toUpperCase().equals((name).toUpperCase())) {
					target = m;
					break;
				}
			}
			if (target == null)
				throw new RuntimeException("No such getter method");
			Object ret = target.invoke(context, new Object[0]);
			return ret;
		} catch (Exception e) {
			// e.printStackTrace();
			 System.out.println("AnnotationHelper->getter() " +
			 e.getMessage());
		}
		try {
			Field target = findField(name, context);
			if (target == null)
				return null;
			return target.get(context);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static Object getter(Object context, String name) {
		Class clazz = context.getClass();
		try {
			Method method[] = clazz.getMethods();
			Method target = null;
			for (Method m : method) {
				if (m.getName().toUpperCase().equals(
						("get" + name).toUpperCase())) {
					target = m;
					break;
				}
			}
			if (target == null)
				throw new RuntimeException("No such getter method");
			Object ret = target.invoke(context, new Object[0]);
			return ret;
		} catch (Exception e) {
			// e.printStackTrace();
			// System.out.println("AnnotationHelper->getter() " +
			// e.getMessage());
		}
		try {
			Field target = findField(name, context);
			if (target == null)
				return null;
			return target.get(context);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private static Field findField(String name, Object context) {
		Class current = context.getClass();
		while (current != null) {
			// System.out.println("On Class:"+current.getName());
			for (Field f : current.getDeclaredFields()) {
				if (!f.getName().equalsIgnoreCase(name))
					continue;
				// Check if this field contain property map
				// annotation
				// PropertyMap pmap = null;
				// for (Object obj : f.getAnnotations()) {
				// if (obj instanceof PropertyMap) {
				// pmap = (PropertyMap) obj;
				// break;
				// }
				// }
				// // Not annotated with propertyMap
				// if (pmap == null)
				// continue;
				return f;
			}
			current = current.getSuperclass();
		}
		return null;
	}

	public static Object convert(Class in, Class out, Object oin) {
		Object oout = null;
		if (out == String.class)
			return oin.toString();
		if (out == Integer.class || out == int.class)
			return new Integer(oin.toString());
		if (out == Float.class || out == float.class)
			return new Float(oin.toString());
		if (out == Double.class || out == double.class)
			return new Double(oin.toString());
		throw new RuntimeException(
				"AnnotationHelper->convert() Don't know how to convert from "
						+ in.getName() + " to " + out.getName());
	}

	public static void setter(Object context, String name, Object value)
			throws Exception {
		Class clazz = context.getClass();

		// try {
		Method method[] = clazz.getMethods();
		Method target = null;
		for (Method m : method) {
			if (m.getName().equalsIgnoreCase("set" + name)) {
				target = m;
				break;
			}
		}
		if (target == null)
			throw new RuntimeException("No such setter method->" + name);
		Class out = target.getParameterTypes()[0];
		Class in = value.getClass();
		value = convert(in, out, value);
		target.invoke(context, new Object[] { value });

		// if (context instanceof AnimationObject) {
		// ((AnimationObject) context).cacheValue(name, value);
		// }
		// } catch (Exception e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// System.exit(0);
		// }
	}

	//
	// public static Object putAnnotation(Object key, Object value) {
	// // System.out.println("Store "+key+" -> "+value);
	// if (annotationRepository.get(key) != null)
	// throw new RuntimeException(
	// "Duplicate Signature storing function annotation");
	// annotationRepository.put(key, value);
	// return value;
	// }
	//
	// public static Object getAnnotation(Object key) {
	// return annotationRepository.get(key);
	// }
	//
	// public static ObjectMap getObjectMapAnnotation(String clazz) {
	// try {
	// for (Annotation annotation : Class.forName(clazz).getAnnotations()) {
	// if (annotation instanceof ObjectMap)
	// return (ObjectMap) annotation;
	// }
	// } catch (Exception e) {
	// e.printStackTrace();
	// }
	// return null;
	// }
	//
	// public static FunctionMap getFunctionMapAnnotation(String clazz,
	// String function, Class[] paramType) {
	// try {
	// Method target = null;
	// target = Class.forName(clazz)
	// .getDeclaredMethod(function, paramType);
	// // for (Method method : Class.forName(clazz).getDeclaredMethods() {
	// // if (method.getName().equals(function))
	// // target = method;
	// // }
	// if (target == null)
	// return null;
	// for (Annotation annotation : target.getAnnotations()) {
	// if (annotation instanceof FunctionMap)
	// return (FunctionMap) annotation;
	// }
	// } catch (Exception e) {
	// e.printStackTrace();
	// }
	// return null;
	// }
	//
	// public static ConstructMap getConstructionMapAnnotation(String clazz,
	// Class[] paramType) {
	// try {
	// Constructor target = null;
	// target = Class.forName(clazz).getDeclaredConstructor(paramType);
	// // for (Constructor method :
	// // Class.forName(clazz).getDeclaredConstructors()) {
	// // if (method.getName().equals(function))
	// // target = method;
	// // }
	// if (target == null)
	// return null;
	// for (Annotation annotation : target.getAnnotations()) {
	// if (annotation instanceof ConstructMap)
	// return (ConstructMap) annotation;
	// }
	// } catch (Exception e) {
	// // TODO Auto-generated catch block
	// e.printStackTrace();
	// }
	// return null;
	// }
	//
	// public static Param[] getConstructorParamAnnotation(String clazz,
	// Class[] paramType) {
	// try {
	// Constructor target = null;
	// target = Class.forName(clazz).getDeclaredConstructor(paramType);
	// // for (Method method : Class.forName(clazz).getDeclaredMethods()) {
	// // if (method.getName().equals(function))
	// // target = method;
	// // }
	// if (target == null)
	// return null;
	//
	// Annotation paramAnnotation[][] = target.getParameterAnnotations();
	// Param param[] = new Param[paramAnnotation.length];
	// for (int i = 0; i < param.length; i++) {
	// for (Annotation an : paramAnnotation[i]) {
	// if (an instanceof Param) {
	// param[i] = (Param) an;
	// }
	// }
	// }
	// return param;
	// } catch (Exception e) {
	// // TODO Auto-generated catch block
	// e.printStackTrace();
	// }
	// return null;
	// }
	//
	// public static Param[] getParameterAnnotation(String clazz, String
	// function,
	// Class[] paramType) {
	// try {
	// Method target = null;
	// target = Class.forName(clazz)
	// .getDeclaredMethod(function, paramType);
	// // for (Method method : Class.forName(clazz).getDeclaredMethods()) {
	// // if (method.getName().equals(function))
	// // target = method;
	// // }
	// if (target == null)
	// return null;
	//
	// Annotation paramAnnotation[][] = target.getParameterAnnotations();
	// Param param[] = new Param[paramAnnotation.length];
	// for (int i = 0; i < param.length; i++) {
	// for (Annotation an : paramAnnotation[i]) {
	// if (an instanceof Param) {
	// param[i] = (Param) an;
	// }
	// }
	// }
	// return param;
	// } catch (Exception e) {
	// // TODO Auto-generated catch block
	// e.printStackTrace();
	// }
	// return null;
	// }

	public static void main(String s[]) {
	}
}
